Update to rust master
authorAlex Crichton <alex@alexcrichton.com>
Fri, 31 Oct 2014 16:37:44 +0000 (09:37 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Fri, 31 Oct 2014 16:37:44 +0000 (09:37 -0700)
16 files changed:
Cargo.lock
src/bin/bench.rs
src/bin/test.rs
src/cargo/core/shell.rs
src/cargo/lib.rs
src/cargo/ops/cargo_clean.rs
src/cargo/ops/cargo_compile.rs
src/cargo/ops/cargo_generate_lockfile.rs
src/cargo/ops/cargo_read_manifest.rs
src/cargo/ops/cargo_rustc/job_queue.rs
src/cargo/ops/cargo_rustc/mod.rs
src/cargo/util/config.rs
src/cargo/util/dependency_queue.rs
src/cargo/util/errors.rs
src/cargo/util/result.rs
tests/test_shell.rs

index 23e5cac16189721735df10a985fb185b0da17dd3..1c3bcdb278848b287d4e5b94e7261ef11529fac0 100644 (file)
@@ -44,12 +44,12 @@ source = "git+https://github.com/lifthrasiir/rust-encoding#6daaad9f4c0fcde452582
 [[package]]
 name = "flate2"
 version = "0.0.1"
-source = "git+https://github.com/alexcrichton/flate2-rs#f74a1f632c09e4f241ecb638e331c2cec4e955e0"
+source = "git+https://github.com/alexcrichton/flate2-rs#67be37548937c059370ce272efe1142fbf198d67"
 
 [[package]]
 name = "git2"
 version = "0.0.1"
-source = "git+https://github.com/alexcrichton/git2-rs#fc308a305068392b07999b7c47122244b151cdec"
+source = "git+https://github.com/alexcrichton/git2-rs#35a0632e92d63de8218675a17cd81e15d0de44b4"
 dependencies = [
  "libgit2 0.0.1 (git+https://github.com/alexcrichton/git2-rs)",
  "url 0.1.0 (git+https://github.com/servo/rust-url)",
@@ -68,7 +68,7 @@ source = "git+https://github.com/carllerche/hamcrest-rust.git#998036d000095f72c8
 [[package]]
 name = "libgit2"
 version = "0.0.1"
-source = "git+https://github.com/alexcrichton/git2-rs#fc308a305068392b07999b7c47122244b151cdec"
+source = "git+https://github.com/alexcrichton/git2-rs#35a0632e92d63de8218675a17cd81e15d0de44b4"
 dependencies = [
  "libssh2-static-sys 0.0.1 (git+https://github.com/alexcrichton/libssh2-static-sys)",
  "link-config 0.0.1 (git+https://github.com/alexcrichton/link-config)",
@@ -83,7 +83,7 @@ source = "git+https://github.com/alexcrichton/libssh2-static-sys#80e71a3021618eb
 [[package]]
 name = "link-config"
 version = "0.0.1"
-source = "git+https://github.com/alexcrichton/link-config#ed9fffa15fc41e8f09e92c7756feead1b0cbb01d"
+source = "git+https://github.com/alexcrichton/link-config#7c56ef12c8a49bedb0357e2a50af9ba79bf0ae1b"
 
 [[package]]
 name = "openssl-static-sys"
@@ -100,17 +100,17 @@ dependencies = [
 [[package]]
 name = "semver"
 version = "0.1.0"
-source = "git+https://github.com/rust-lang/semver#fdaec35ff5db609f53119f1e455fdd8830edc790"
+source = "git+https://github.com/rust-lang/semver#7dca047a9cd40e929a4545b37a1917daff82f156"
 
 [[package]]
 name = "tar"
 version = "0.0.1"
-source = "git+https://github.com/alexcrichton/tar-rs#fced2e3833ed2776d9975ffc6fb3204528944faa"
+source = "git+https://github.com/alexcrichton/tar-rs#47d2cc4b09e373a4cc7bee7c71ebf96b42ea620d"
 
 [[package]]
 name = "toml"
 version = "0.1.0"
-source = "git+https://github.com/alexcrichton/toml-rs#35804927ef76cc5f24b04f2af25919c488a0992c"
+source = "git+https://github.com/alexcrichton/toml-rs#71d1689d63ef1af41addef330e314a56e88f48a9"
 
 [[package]]
 name = "url"
index 56e441cfa6e99f425fe57212a86d3d7e5df56226..612c37b1534092bf2f432f3eb15ead83e836ee56 100644 (file)
@@ -75,7 +75,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
         Some(err) => {
             Err(match err.exit {
                 Some(ExitStatus(i)) => CliError::new("", i as uint),
-                _ => CliError::from_boxed(err.mark_human(), 101)
+                _ => CliError::from_boxed(err.concrete().mark_human(), 101)
             })
         }
     }
index 0dd4d4c3066b731a26b2e212c946b8fadbd4cdec..b1261a6dd8218f7f8d12b61404ab4ac14d0b4e25 100644 (file)
@@ -74,7 +74,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
         Some(err) => {
             Err(match err.exit {
                 Some(ExitStatus(i)) => CliError::new("", i as uint),
-                _ => CliError::from_boxed(err.mark_human(), 101)
+                _ => CliError::from_boxed(err.concrete().mark_human(), 101)
             })
         }
     }
index b5570f0ddb1409dd628613f5f158b39f01810797..3ee6a916f7d80099b51aa9c52ff058ee93a5f4a6 100644 (file)
@@ -1,4 +1,4 @@
-use term::{mod, Terminal, color};
+use term::{Terminal, TerminfoTerminal, color};
 use term::color::{Color, BLACK, RED, GREEN, YELLOW};
 use term::attr::{Attr, Bold};
 use std::io::{IoResult, stderr};
@@ -10,34 +10,38 @@ pub struct ShellConfig {
     pub tty: bool
 }
 
-enum AdequateTerminal<'a> {
-    NoColor(Box<Writer+'a>),
-    Colored(Box<Terminal<Box<Writer+'a>>+'a>)
+enum AdequateTerminal {
+    NoColor(Box<Writer + Send>),
+    Colored(Box<Terminal<UghWhyIsThisNecessary> + Send>)
 }
 
-pub struct Shell<'a> {
-    terminal: AdequateTerminal<'a>,
-    config: ShellConfig
+pub struct Shell {
+    terminal: AdequateTerminal,
+    config: ShellConfig,
 }
 
-pub struct MultiShell<'a> {
-    out: Shell<'a>,
-    err: Shell<'a>,
+pub struct MultiShell {
+    out: Shell,
+    err: Shell,
     verbose: bool
 }
 
 pub type Callback<'a> = |&mut MultiShell|:'a -> IoResult<()>;
 
-impl<'a> MultiShell<'a> {
-    pub fn new(out: Shell<'a>, err: Shell<'a>, verbose: bool) -> MultiShell<'a> {
+struct UghWhyIsThisNecessary {
+    inner: Box<Writer + Send>,
+}
+
+impl MultiShell {
+    pub fn new(out: Shell, err: Shell, verbose: bool) -> MultiShell {
         MultiShell { out: out, err: err, verbose: verbose }
     }
 
-    pub fn out(&mut self) -> &mut Shell<'a> {
+    pub fn out(&mut self) -> &mut Shell {
         &mut self.out
     }
 
-    pub fn err(&mut self) -> &mut Shell<'a> {
+    pub fn err(&mut self) -> &mut Shell {
         &mut self.err
     }
 
@@ -72,20 +76,21 @@ impl<'a> MultiShell<'a> {
     }
 }
 
-pub type ShellCallback<'a> = |&mut Shell<'a>|:'a -> IoResult<()>;
+pub type ShellCallback<'a> = |&mut Shell|:'a -> IoResult<()>;
 
-impl<'a> Shell<'a> {
-    pub fn create(out: Box<Writer+'a>, config: ShellConfig) -> Shell<'a> {
+impl Shell {
+    pub fn create(out: Box<Writer + Send>, config: ShellConfig) -> Shell {
+        let out = UghWhyIsThisNecessary { inner: out };
         if config.tty && config.color {
-            let term: Option<term::TerminfoTerminal<Box<Writer+'a>>> = Terminal::new(out);
+            let term = TerminfoTerminal::new(out);
             term.map(|t| Shell {
-                terminal: Colored(box t as Box<Terminal<Box<Writer+'a>>>),
+                terminal: Colored(t),
                 config: config
             }).unwrap_or_else(|| {
-                Shell { terminal: NoColor(box stderr() as Box<Writer+'a>), config: config }
+                Shell { terminal: NoColor(box stderr()), config: config }
             })
         } else {
-            Shell { terminal: NoColor(out), config: config }
+            Shell { terminal: NoColor(out.inner), config: config }
         }
     }
 
@@ -119,19 +124,6 @@ impl<'a> Shell<'a> {
         try!(self.flush());
         Ok(())
     }
-}
-
-impl<'a> Terminal<Box<Writer+'a>> for Shell<'a> {
-    fn new(out: Box<Writer+'a>) -> Option<Shell<'a>> {
-        Some(Shell {
-            terminal: NoColor(out),
-            config: ShellConfig {
-                color: true,
-                verbose: false,
-                tty: false,
-            }
-        })
-    }
 
     fn fg(&mut self, color: color::Color) -> IoResult<bool> {
         match self.terminal {
@@ -140,13 +132,6 @@ impl<'a> Terminal<Box<Writer+'a>> for Shell<'a> {
         }
     }
 
-    fn bg(&mut self, color: color::Color) -> IoResult<bool> {
-        match self.terminal {
-            Colored(ref mut c) => c.bg(color),
-            NoColor(_) => Ok(false)
-        }
-    }
-
     fn attr(&mut self, attr: Attr) -> IoResult<bool> {
         match self.terminal {
             Colored(ref mut c) => c.attr(attr),
@@ -167,27 +152,9 @@ impl<'a> Terminal<Box<Writer+'a>> for Shell<'a> {
             NoColor(_) => Ok(())
         }
     }
-
-    fn unwrap(self) -> Box<Writer+'a> {
-        panic!("Can't unwrap a Shell");
-    }
-
-    fn get_ref<'b>(&'b self) -> &'b Box<Writer+'a> {
-        match self.terminal {
-            Colored(ref c) => c.get_ref(),
-            NoColor(ref w) => w
-        }
-    }
-
-    fn get_mut<'b>(&'b mut self) -> &'b mut Box<Writer+'a> {
-        match self.terminal {
-            Colored(ref mut c) => c.get_mut(),
-            NoColor(ref mut w) => w
-        }
-    }
 }
 
-impl<'a> Writer for Shell<'a> {
+impl Writer for Shell {
     fn write(&mut self, buf: &[u8]) -> IoResult<()> {
         match self.terminal {
             Colored(ref mut c) => c.write(buf),
@@ -202,3 +169,9 @@ impl<'a> Writer for Shell<'a> {
         }
     }
 }
+
+impl Writer for UghWhyIsThisNecessary {
+    fn write(&mut self, bytes: &[u8]) -> IoResult<()> {
+        self.inner.write(bytes)
+    }
+}
index 17a84c7b323da643b1be4b54313d4ad1afabd175..800f2d59d043a2e0bf1b1e2a09af86292e750033 100644 (file)
@@ -150,15 +150,15 @@ pub fn process_executed<'a,
     }
 }
 
-pub fn shell(verbose: bool) -> MultiShell<'static> {
+pub fn shell(verbose: bool) -> MultiShell {
     let tty = stderr_raw().isatty();
-    let stderr = box stderr() as Box<Writer>;
+    let stderr = box stderr() as Box<Writer + Send>;
 
     let config = ShellConfig { color: true, verbose: verbose, tty: tty };
     let err = Shell::create(stderr, config);
 
     let tty = stdout_raw().isatty();
-    let stdout = box stdout() as Box<Writer>;
+    let stdout = box stdout() as Box<Writer + Send>;
 
     let config = ShellConfig { color: true, verbose: verbose, tty: tty };
     let out = Shell::create(stdout, config);
index 881ebf342b0d797e3f968532f88e795847f1d262..0560225a3818b623468fcfd4997c091d463dd77a 100644 (file)
@@ -9,7 +9,7 @@ use ops::{mod, Layout, Context};
 pub struct CleanOptions<'a> {
     pub spec: Option<&'a str>,
     pub target: Option<&'a str>,
-    pub shell: &'a mut MultiShell<'a>
+    pub shell: &'a mut MultiShell,
 }
 
 /// Cleans the project from build artifacts.
index 8e44a81d810d75661646291b871470a263d302ca..18ed9328d0ca57fff1bb1ca2525584420031a6e0 100644 (file)
@@ -36,7 +36,7 @@ use util::{CargoResult, Wrap, config, internal, human, ChainError, profile};
 /// Contains informations about how a package should be compiled.
 pub struct CompileOptions<'a> {
     pub env: &'a str,
-    pub shell: &'a mut MultiShell<'a>,
+    pub shell: &'a mut MultiShell,
     /// Number of concurrent jobs to use.
     pub jobs: Option<uint>,
     /// The target platform to compile for (example: `i686-unknown-linux-gnu`).
index 059e9064c16268b6b161d03c72187243d7df033a..19cfdee2a4ba5562ebf0c6b390c86bc6854ef3a9 100644 (file)
@@ -9,7 +9,7 @@ use util::config::{Config};
 use util::{CargoResult, human};
 
 pub struct UpdateOptions<'a> {
-    pub shell: &'a mut MultiShell<'a>,
+    pub shell: &'a mut MultiShell,
     pub to_update: Option<&'a str>,
     pub precise: Option<&'a str>,
     pub aggressive: bool,
index bdaa89b8b10658e6aa8a7fd120e5c62ab174f638..955c15bcc413368fb225f4189f31c458faffa6e4 100644 (file)
@@ -3,7 +3,7 @@ use std::io::{mod, File, fs};
 use std::io::fs::PathExtensions;
 
 use core::{Package,Manifest,SourceId};
-use util::{mod, CargoResult, human, CargoError};
+use util::{mod, CargoResult, human, FromError};
 use util::important_paths::find_project_manifest_exact;
 use util::toml::{Layout, project_layout};
 
@@ -66,7 +66,7 @@ fn walk(path: &Path, is_root: bool,
         let dirs = match fs::readdir(path) {
             Ok(dirs) => dirs,
             Err(ref e) if e.kind == io::PermissionDenied => return Ok(()),
-            Err(e) => return Err(e.box_error()),
+            Err(e) => return Err(FromError::from_error(e)),
         };
         for dir in dirs.iter() {
             try!(walk(dir, false, |a, x| callback(a, x)))
index 14df4eeaa78c4ee2b166c455ccfda9f022f9e6a1..9c1b5f7b81904abf90805301660cb09181dea00a 100644 (file)
@@ -124,7 +124,7 @@ impl<'a, 'b> JobQueue<'a, 'b> {
             self.active -= 1;
             match result {
                 Ok(()) => {
-                    let state = self.pending.get_mut(&(id, stage));
+                    let state = &mut self.pending[(id, stage)];
                     state.amt -= 1;
                     state.fresh = state.fresh.combine(fresh);
                     if state.amt == 0 {
index 05e3c0d0a99c0167a16fae43fc007299fb19eaef..ee023be19fc9562aa46ed1bf081e903598f53e26 100644 (file)
@@ -277,7 +277,7 @@ fn compile_custom(pkg: &Package, cmd: &str,
         try!(p.exec_with_output().map(|_| ()).map_err(|mut e| {
             e.msg = format!("Failed to run custom build command for `{}`\n{}",
                             pkg, e.msg);
-            e.mark_human()
+            e.concrete().mark_human()
         }));
         Ok(())
     })
index 20c37f3c9e3a4d67fd50380a57a5067164955a90..bbb8575624762fa82c138383c0462c35446c96eb 100644 (file)
@@ -14,7 +14,7 @@ use util::toml as cargo_toml;
 
 pub struct Config<'a> {
     home_path: Path,
-    shell: &'a mut MultiShell<'a>,
+    shell: &'a mut MultiShell,
     jobs: uint,
     target: Option<string::String>,
     linker: Option<string::String>,
index a07c598ef57e0a6f2f365318e72ca604e2445206..1807ed284640355c1888146baf9fb6e52d296991 100644 (file)
@@ -125,7 +125,7 @@ impl<C, K: Dependency<C>, V> DependencyQueue<K, V> {
             if fresh == Dirty {
                 self.dirty.insert(dep.clone());
             }
-            assert!(self.dep_map.get_mut(dep).mut0().remove(key));
+            assert!(self.dep_map[*dep].mut0().remove(key));
         }
     }
 }
index 3653a491d25508eab0e2e354dde7be0f8097d53d..0c6132514b69e317f9702d4e4ef870461cce1cf4 100644 (file)
@@ -17,14 +17,6 @@ pub trait CargoError: Send {
     fn cause(&self) -> Option<&CargoError> { None }
     fn is_human(&self) -> bool { false }
 
-    fn to_error<E: FromError<Self>>(self) -> E {
-        FromError::from_error(self)
-    }
-
-    fn box_error(self) -> Box<CargoError + Send> {
-        box self as Box<CargoError + Send>
-    }
-
     fn concrete(&self) -> ConcreteCargoError {
         ConcreteCargoError {
             description: self.description(),
@@ -33,18 +25,6 @@ pub trait CargoError: Send {
             is_human: self.is_human()
         }
     }
-
-    fn with_cause<E: CargoError + Send>(self, cause: E) -> Box<CargoError + Send> {
-        let mut concrete = self.concrete();
-        concrete.cause = Some(cause.box_error());
-        box concrete as Box<CargoError + Send>
-    }
-
-    fn mark_human(self) -> Box<CargoError + Send> {
-        let mut concrete = self.concrete();
-        concrete.is_human = true;
-        box concrete as Box<CargoError + Send>
-    }
 }
 
 pub trait FromError<E> {
@@ -53,7 +33,7 @@ pub trait FromError<E> {
 
 impl<E: CargoError + Send> FromError<E> for Box<CargoError + Send> {
     fn from_error(error: E) -> Box<CargoError + Send> {
-        error.box_error()
+        box error as Box<CargoError + Send>
     }
 }
 
@@ -75,25 +55,10 @@ impl Show for Box<CargoError + Send> {
 }
 
 impl CargoError for Box<CargoError + Send> {
-    fn description(&self) -> String {
-        (**self).description()
-    }
-
-    fn detail(&self) -> Option<String> {
-        (**self).detail()
-    }
-
-    fn cause(&self) -> Option<&CargoError> {
-        (**self).cause()
-    }
-
-    fn is_human(&self) -> bool {
-        (**self).is_human()
-    }
-
-    fn box_error(self) -> Box<CargoError + Send> {
-        self
-    }
+    fn description(&self) -> String { (**self).description() }
+    fn detail(&self) -> Option<String> { (**self).detail() }
+    fn cause(&self) -> Option<&CargoError> { (**self).cause() }
+    fn is_human(&self) -> bool { (**self).is_human() }
 }
 
 impl CargoError for semver::ReqParseError {
@@ -114,19 +79,19 @@ pub trait ChainError<T> {
 
 impl<'a, T> ChainError<T> for ||:'a -> CargoResult<T> {
     fn chain_error<E: CargoError + Send>(self, callback: || -> E) -> CargoResult<T> {
-        self().map_err(|err| callback().with_cause(err))
+        self().map_err(|err| callback().concrete().with_cause(err))
     }
 }
 
 impl<T, E: CargoError + Send> BoxError<T> for Result<T, E> {
     fn box_error(self) -> CargoResult<T> {
-        self.map_err(|err| err.box_error())
+        self.map_err(|err| box err as Box<CargoError + Send>)
     }
 }
 
 impl<T, E: CargoError + Send> ChainError<T> for Result<T, E> {
     fn chain_error<E: CargoError + Send>(self, callback: || -> E) -> CargoResult<T>  {
-        self.map_err(|err| callback().with_cause(err))
+        self.map_err(|err| callback().concrete().with_cause(err))
     }
 }
 
@@ -222,12 +187,6 @@ impl CargoError for ProcessError {
     fn cause(&self) -> Option<&CargoError> {
         self.cause.as_ref().map(|c| { let err: &CargoError = &**c; err })
     }
-
-    fn with_cause<E: CargoError + Send>(mut self,
-                                        err: E) -> Box<CargoError + Send> {
-        self.cause = Some(err.box_error());
-        box self as Box<CargoError + Send>
-    }
 }
 
 pub struct ConcreteCargoError {
@@ -237,6 +196,19 @@ pub struct ConcreteCargoError {
     is_human: bool
 }
 
+impl ConcreteCargoError {
+    pub fn with_cause<E: CargoError + Send>(mut self,
+                                            err: E) -> Box<CargoError + Send> {
+        self.cause = Some(box err as Box<CargoError + Send>);
+        box self as Box<CargoError + Send>
+    }
+
+    pub fn mark_human(mut self) -> Box<CargoError + Send> {
+        self.is_human = true;
+        box self as Box<CargoError + Send>
+    }
+}
+
 impl Show for ConcreteCargoError {
     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
         write!(f, "{}", self.description)
@@ -256,17 +228,6 @@ impl CargoError for ConcreteCargoError {
         self.cause.as_ref().map(|c| { let err: &CargoError = &**c; err })
     }
 
-    fn with_cause<E: CargoError + Send>(mut self,
-                                        err: E) -> Box<CargoError + Send> {
-        self.cause = Some(err.box_error());
-        box self as Box<CargoError + Send>
-    }
-
-    fn mark_human(mut self) -> Box<CargoError + Send> {
-        self.is_human = true;
-        box self as Box<CargoError + Send>
-    }
-
     fn is_human(&self) -> bool {
         self.is_human
     }
@@ -385,7 +346,7 @@ pub fn caused_human<S: Show, E: CargoError + Send>(error: S, cause: E) -> Box<Ca
     box ConcreteCargoError {
         description: error.to_string(),
         detail: None,
-        cause: Some(cause.box_error()),
+        cause: Some(box cause as Box<CargoError + Send>),
         is_human: true
     } as Box<CargoError + Send>
 }
index 108e08488d441feb3e7f2a84b82d7bc47a96a49e..e415f728866490b654c8747a3d4b366a896bb599 100644 (file)
@@ -8,7 +8,7 @@ impl<T> Wrap for Result<T, Box<CargoError + Send>> {
     fn wrap<E: CargoError + Send>(self, error: E) -> CargoResult<T> {
         match self {
             Ok(x) => Ok(x),
-            Err(e) => Err(error.with_cause(e))
+            Err(e) => Err(error.concrete().with_cause(e))
         }
     }
 }
index d1211ab2bacbe54109c6ea1b6ffda92cce0fe2dd..a500d0827e005648141ff0368c52a754271a030e 100644 (file)
@@ -1,55 +1,60 @@
-use support::{ResultTest,Tap,shell_writes};
+use std::io::{MemWriter, IoResult, ChanReader, ChanWriter};
+use term::{Terminal, TerminfoTerminal, color};
 use hamcrest::{assert_that};
-use std::io::{MemWriter, BufWriter, IoResult};
+
 use cargo::core::shell::{Shell,ShellConfig};
-use term::{Terminal,TerminfoTerminal,color};
+
+use support::{ResultTest,Tap,shell_writes};
 
 fn setup() {
 }
 
-fn writer(buf: &mut [u8]) -> Box<Writer> {
-    box BufWriter::new(buf) as Box<Writer>
+fn pair() -> (ChanWriter, ChanReader) {
+    let (tx, rx) = channel();
+    (ChanWriter::new(tx), ChanReader::new(rx))
 }
 
 test!(non_tty {
     let config = ShellConfig { color: true, verbose: true, tty: false };
-    let mut buf: Vec<u8> = Vec::from_elem(9, 0 as u8);
+    let (tx, mut rx) = pair();
 
-    Shell::create(writer(buf.as_mut_slice()), config).tap(|shell| {
+    Shell::create(box tx, config).tap(|shell| {
         shell.say("Hey Alex", color::RED).assert();
-        assert_that(buf.as_slice(), shell_writes("Hey Alex\n"));
     });
+
+    let buf = rx.read_to_end().unwrap();
+    assert_that(buf.as_slice(), shell_writes("Hey Alex\n"));
 })
 
 test!(color_explicitly_disabled {
     let config = ShellConfig { color: false, verbose: true, tty: true };
-    let mut buf: Vec<u8> = Vec::from_elem(9, 0 as u8);
+    let (tx, mut rx) = pair();
 
-    Shell::create(writer(buf.as_mut_slice()), config).tap(|shell| {
+    Shell::create(box tx, config).tap(|shell| {
         shell.say("Hey Alex", color::RED).assert();
-        assert_that(buf.as_slice(), shell_writes("Hey Alex\n"));
     });
+    let buf = rx.read_to_end().unwrap();
+    assert_that(buf.as_slice(), shell_writes("Hey Alex\n"));
 })
 
 test!(colored_shell {
-    let term: Option<TerminfoTerminal<MemWriter>> =
-        Terminal::new(MemWriter::new());
+    let term = TerminfoTerminal::new(MemWriter::new());
     if term.is_none() { return }
 
     let config = ShellConfig { color: true, verbose: true, tty: true };
-    let mut buf: Vec<u8> = Vec::from_elem(100, 0 as u8);
+    let (tx, mut rx) = pair();
 
-    Shell::create(writer(buf.as_mut_slice()), config).tap(|shell| {
+    Shell::create(box tx, config).tap(|shell| {
         shell.say("Hey Alex", color::RED).assert();
-        let buf = buf.as_slice().slice_to(buf.iter().position(|a| *a == 0).unwrap());
-        assert_that(buf, shell_writes(colored_output("Hey Alex\n",
-                                                     color::RED).assert()));
     });
+    let buf = rx.read_to_end().unwrap();
+    assert_that(buf.as_slice(),
+                shell_writes(colored_output("Hey Alex\n",
+                                            color::RED).assert()));
 })
 
 fn colored_output<S: Str>(string: S, color: color::Color) -> IoResult<String> {
-    let mut term: TerminfoTerminal<MemWriter> =
-        Terminal::new(MemWriter::new()).assert();
+    let mut term = TerminfoTerminal::new(MemWriter::new()).unwrap();
     try!(term.reset());
     try!(term.fg(color));
     try!(term.write_str(string.as_slice()));